package com.yonyou.crm.sact.visitrule.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.yonyou.crm.common.biz.service.BaseBizServiceImpl;
import com.yonyou.crm.common.enumeration.entity.EnumVO;
import com.yonyou.crm.common.enumeration.entity.WhetherEnum;
import com.yonyou.crm.common.enumeration.service.EnumBizServiceImpl;
import com.yonyou.crm.common.exception.CrmBusinessException;
import com.yonyou.crm.common.field.handler.FieldRelationHandler;
import com.yonyou.crm.common.field.relation.EnumFieldRelation;
import com.yonyou.crm.common.field.relation.FieldRelation;
import com.yonyou.crm.common.field.relation.RefFieldRelation;
import com.yonyou.crm.common.page.entity.Page;
import com.yonyou.crm.sact.taskcard.entity.SactTaskcardVO;
import com.yonyou.crm.sact.taskcard.service.SactTaskcardBizServiceImpl;
import com.yonyou.crm.sact.visitrule.entity.RefIndexEnum;
import com.yonyou.crm.sact.visitrule.entity.VisitruleTaskcardVO;
import com.yonyou.crm.sact.visitrule.entity.VisitruleVO;
import com.yonyou.crm.sys.org.service.SysOrgBizServiceImpl;
import com.yonyou.iuap.context.InvocationInfoProxy;

@Service
public class VisitruleBizServiceImpl extends BaseBizServiceImpl<VisitruleVO> {
	
	@Autowired
	private SysOrgBizServiceImpl orgService;
	@Autowired
	private SactTaskcardBizServiceImpl tcService;
	@Autowired
	private EnumBizServiceImpl enumService;
	
	/**
	 * 查询拜访规则
	 * @param page
	 * @param paramMap
	 * @return
	 */
	public Page<VisitruleVO> getVisitruleList(Page<VisitruleVO> page,Map<String, Object> paramMap) {

		Page<VisitruleVO> visitrulePage = null;
		if (paramMap != null) {
			
			paramMap.put("tenantId", new Long(InvocationInfoProxy.getTenantid()));
			//参考指标从全局参数中获取
			paramMap.put("refIndex", 1);
			visitrulePage = super.pageSelect(VisitruleVO.class, page, paramMap.keySet().toArray(new String[0]), paramMap.values().toArray(new Object[0]));
		}
		else {
			visitrulePage = super.pageSelect(VisitruleVO.class, page, null, null);
		}
		
		trans(visitrulePage.getData());
		
		return visitrulePage;
	}

	@Override
	protected void beforeSaveVO(VisitruleVO vo) { 
		
		int nameCount = getCountByName(vo.getName());
		if (nameCount > 0) {
			throw new CrmBusinessException("名称已存在，保存失败。");
		}
		
		super.beforeSaveVO(vo);
		
		setCumValue(vo);
	}
	
	@Override
	public VisitruleVO saveVO(VisitruleVO vo) {
		
		vo = super.saveVO(vo);
		
		trans(Arrays.asList(vo));
		
		return vo;
	}
	
	@Override
	protected void afterSaveVO(VisitruleVO vo) {
		
		if (vo != null) {
			//保存拜访卡
			saveVT(vo.getTaskcardList(), vo.getId());
		}
	}
	
	/**
	 * 新增拜访规则任务卡
	 * @param vtVOs
	 * @param visitruleId
	 */
	private void saveVT(List<VisitruleTaskcardVO> vtVOs, Long visitruleId) {

		if (vtVOs != null && vtVOs.size() > 0) {

			Iterator<VisitruleTaskcardVO> it = vtVOs.iterator();
			int orderNum = 1;
			
			while(it.hasNext()){
				
				VisitruleTaskcardVO vtVO = it.next();
				
				vtVO.setVisitruleId(visitruleId);
				//根据数组顺序设置显示顺序
				vtVO.setOrderNum(orderNum);
				
				if (vtVO.getIsPreseted() == WhetherEnum.YES.getValue()) {
					it.remove();
				}
				else {
					vtVO.setIsPreseted(WhetherEnum.NO.getValue());
				}
				orderNum++;
			}
			if (vtVOs.size() > 0) {
				dao.saveSql(VisitruleVO.class, "insertVT", vtVOs);
			}
		}
	}
	
	/**
	 * 删除拜访规则任务卡
	 * @param visitruleId
	 */
	private void deleteVT(Long visitruleId) {
		dao.deleteSql(VisitruleVO.class, "deleteVT", visitruleId);
	}
	
	@Override
	protected void beforeUpdateVO(VisitruleVO vo) {
		
		super.beforeUpdateVO(vo);
		
		setCumValue(vo);
	}
	
	public VisitruleVO updateVO(VisitruleVO vo) { 
		
		vo = super.updateVO(vo);
		
		trans(Arrays.asList(vo));
		
		return vo;
	}
	
	@Override
	protected void afterUpdateVO(VisitruleVO vo) {
		
		if (vo != null) {
			//修改拜访卡
			deleteVT(vo.getId());
			saveVT(vo.getTaskcardList(), vo.getId());
		}
	}
	
	public int batchUpdateEnableState(String[] ids, Integer enableState) {
		
		Map<String, Object> enableParaMap = new HashMap<String, Object>();
		enableParaMap.put("ids", ids);
		enableParaMap.put("enableState", enableState);
		enableParaMap.put("enableUserId", new Long(InvocationInfoProxy.getParameter("id")));
		enableParaMap.put("enableTime", new Date());
				
		return dao.updateSql(VisitruleVO.class, "batchUpdateEnableState", enableParaMap);
	}
	
	/**
	 * 翻译拜访规则实体
	 * @param visitruleList
	 * @return
	 */
	private List<VisitruleVO> trans(List<VisitruleVO> visitruleList) {
		
		if (visitruleList != null && visitruleList.size() > 0) {
			
			List<FieldRelation<VisitruleVO>> relations = new ArrayList<FieldRelation<VisitruleVO>>();
			relations.add(new RefFieldRelation<VisitruleVO>(VisitruleVO.class, "orgId", new String[]{"orgName"}, orgService, "selectFieldsByIds"));
			relations.add(new EnumFieldRelation<VisitruleVO>(VisitruleVO.class, "enableState", "enableStateName", enumService, "enable_state"));
			relations.add(new EnumFieldRelation<VisitruleVO>(VisitruleVO.class, "refIndex", "refIndexName", enumService, "visitrule_ref_index"));
			
			String code = null;
			
			Integer refIndex = visitruleList.get(0).getRefIndex();
			
			if (refIndex == RefIndexEnum.CUMLEVEL.getValue()) {
				code = "cum_level";
			}
			else if (refIndex == RefIndexEnum.CUMTYPE.getValue()) {
				code = "cum_type";
			}
			else if(refIndex == RefIndexEnum.CUMSTATE.getValue()) {
				code = "cum_state";
			}

			if (code != null) {
				relations.add(new EnumFieldRelation<VisitruleVO>(VisitruleVO.class, "cumEnumValue", "cumEnumValueName", enumService, code));
			}
			
			new FieldRelationHandler<VisitruleVO>().handler(visitruleList, relations);
			
			setUncheckedTaskcardList(visitruleList);
		}

		return visitruleList;
	}
	
	/**
	 * 设置未选中的任务卡列表
	 * @param visitruleList
	 */
	private void setUncheckedTaskcardList(List<VisitruleVO> visitruleList) {
		
		//所有任务卡
		List<SactTaskcardVO> allTList = tcService.getRefList(null);

		for (VisitruleVO vo : visitruleList) {

			//选中的任务卡
			List<VisitruleTaskcardVO> checkedList = vo.getTaskcardList();
			
			if (checkedList == null || checkedList.size() == 0) {
				continue;
			}
			
			List<SactTaskcardVO> newAllTList = new ArrayList<SactTaskcardVO>(allTList);
			Iterator<SactTaskcardVO> allIterator = newAllTList.iterator();
			while (allIterator.hasNext()) {
				
				SactTaskcardVO allVO = allIterator.next();
				for (VisitruleTaskcardVO checkedVO : checkedList) {
					
					if (allVO.getId().equals(checkedVO.getTaskcardId())) {
						
						//翻译选中的任务卡名称
						checkedVO.setTaskcardName(allVO.getName());
						checkedVO.setRemark(allVO.getRemark());
						//移除选中的任务卡
						allIterator.remove();
					}
				}
			}

			//设置未选中的任务卡列表
			vo.setUncheckedList(v2vt(newAllTList));
			
			//翻译拜访规则任务卡
			List<FieldRelation<VisitruleTaskcardVO>> vtRelations = new ArrayList<FieldRelation<VisitruleTaskcardVO>>();
			vtRelations.add(new EnumFieldRelation<VisitruleTaskcardVO>(VisitruleTaskcardVO.class, "required", "requiredName", enumService, "whether"));
			new FieldRelationHandler<VisitruleTaskcardVO>().handler(checkedList, vtRelations);

		}
	}
	
	/**
	 * 任务卡转换为拜访规则任务卡，利于前端操作
	 * @param tList
	 * @return
	 */
	private List<VisitruleTaskcardVO> v2vt(List<SactTaskcardVO> tList) {
		
		List<VisitruleTaskcardVO> vtList = new ArrayList<VisitruleTaskcardVO>();
		
		if (tList != null && tList.size() > 0) {
			
			for (SactTaskcardVO tVO : tList) {
				VisitruleTaskcardVO vtVO = new VisitruleTaskcardVO();
				vtVO.setTaskcardId(tVO.getId());
				vtVO.setTaskcardName(tVO.getName());
				vtVO.setRemark(tVO.getRemark());
				vtVO.setRequired(2);
				vtVO.setMtObjId(tVO.getMtObjId());
				vtList.add(vtVO);
			}
		}
		return vtList;
	}
	
	/**
	 * 翻译拜访规则任务卡实体
	 * @param visitruleList
	 * @return
	 */
	private List<VisitruleTaskcardVO> transVTVO(List<VisitruleTaskcardVO> vtList) {
		
		if (vtList != null && vtList.size() > 0) {
			
			List<FieldRelation<VisitruleTaskcardVO>> relations = new ArrayList<FieldRelation<VisitruleTaskcardVO>>();
			relations.add(new RefFieldRelation<VisitruleTaskcardVO>(VisitruleTaskcardVO.class, "taskcardId", new String[]{"taskcardName"}, tcService, "selectFieldsByIds"));
			relations.add(new EnumFieldRelation<VisitruleTaskcardVO>(VisitruleTaskcardVO.class, "required", "requiredName", enumService, "whether"));

			new FieldRelationHandler<VisitruleTaskcardVO>().handler(vtList, relations);
		}

		return vtList;
	}
	
	/**
	 * 根据参考指标给客户相关枚举赋值
	 * @param vo
	 */
	private void setCumValue(VisitruleVO vo) {
		
		if (vo.getRefIndex() == RefIndexEnum.CUMLEVEL.getValue()) {
			vo.setCumLevel(vo.getCumEnumValue());
		}
		else if (vo.getRefIndex() == RefIndexEnum.CUMTYPE.getValue()) {
			vo.setCumType(vo.getCumEnumValue());
		}
		else if (vo.getRefIndex() == RefIndexEnum.CUMSTATE.getValue()) {
			vo.setCumState(vo.getCumEnumValue());
		}

	}
	
	/**
	 * 根据拜访规则id获得部门名称
	 * @param ids
	 * @return
	 */
	public Object selectVisitruleDeptById(Object[] ids) {
		Map<String, Object> para = new HashMap<String, Object>();
		para.put("ids", ids);
		return dao.selectList(VisitruleVO.class, "selectVisitruleDeptById", para);
	}
	
	/**
	 * 根据名称查询拜访规则数量
	 * @param name
	 * @return
	 */
	public int getCountByName(String name) {
		
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("name", name);
		paraMap.put("tenantId", new Long(InvocationInfoProxy.getTenantid()));
		return dao.countAll(VisitruleVO.class, "getCountByName", paraMap);
	}
	
	/**
	 * 根据条件获取拜访规则列表
	 * @param paraMap
	 * @return
	 */
	public List<VisitruleVO> getRefList(Map<String, Object> paraMap) {
		
		if (paraMap == null) {
			paraMap = new HashMap<String, Object>();
		}
		
		paraMap.put("tenantId", new Long(InvocationInfoProxy.getTenantid()));
		
		if (paraMap.containsKey("refIndex") && paraMap.containsKey("cumEnumValue")) {
			
			Integer refIndex = (Integer) paraMap.get("refIndex");
			Integer cumEnumValue = (Integer) paraMap.get("cumEnumValue");
			String code = null;
			
			if (refIndex == RefIndexEnum.CUMLEVEL.getValue()) {
				code = "cumLevel";
			}
			else if (refIndex == RefIndexEnum.CUMTYPE.getValue()) {
				code = "cumType";
			}
			else if (refIndex == RefIndexEnum.CUMSTATE.getValue()) {
				code = "cumState";
			}
			
			if (code != null) {
				
				paraMap.put(code, cumEnumValue);
			}
		}
		
		return dao.selectVoList(VisitruleVO.class, "getRefList", paraMap);
	}
	
	/********拜访规则2.0************/
	/**
	 * 拜访规则列表
	 * @param paraMap
	 * @return
	 */
	public List<VisitruleVO> getList(Map<String, Object> paraMap) {

		if (paraMap == null) {
			paraMap = new HashMap<String, Object>();
		}

		paraMap.put("tenantId", new Long(InvocationInfoProxy.getTenantid()));
		//TODO 参考指标从全局参数中获取
		paraMap.put("refIndex", 1);

		List<VisitruleVO> list = dao.selectVoList(VisitruleVO.class, "listVisitrule", paraMap);

		trans(list);

		return list;
	}
	
	/**
	 * 保存任务卡
	 * @param vtVOs
	 * @param visitruleId
	 */
	public void updateVT(List<VisitruleTaskcardVO> vtVOs, Long visitruleId) {
		
		if (visitruleId != null) {
			deleteVT(visitruleId);
			saveVT(vtVOs, visitruleId);
		}
	}
	
	/**
	 * 保存预置拜访规则
	 * @param orgId
	 */
	public void savePresetedVisitrule(Long orgId) {
				
		if (orgId == null) {	
			return;
		}
		
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("orgId", orgId);
		paraMap.put("tenantId", InvocationInfoProxy.getTenantid());
		
		//校验是否已经生成预置数据
		int count = dao.countAll(VisitruleVO.class, "getCountByOrgId", paraMap);
		if (count > 0) {
			return ;
		}
			
		for (VisitruleVO vo : generateVList(orgId)) {
			
			//保存拜访规则
			vo = dao.save(vo);
			//根据拜访规则id，保存拜访规则任务卡
			dao.saveSql(VisitruleVO.class, "insertVT", getPresetedVTList(vo.getId()));
		}	
	}
	
	/**
	 * 生成拜访规则预置数据
	 * @param orgId
	 * @return
	 */
	private List<VisitruleVO> generateVList(Long orgId) {

		//根据客户等级、客户类型、客户状态生成拜访规则
		Map<String, List<EnumVO>> cumMap = enumService.getEnumByCodes(new String[]{"cum_level","cum_type","cum_state"});

		List<VisitruleVO> voList = new ArrayList<VisitruleVO>();

		getPresetedVList(cumMap.get("cum_level"), RefIndexEnum.CUMLEVEL, orgId, voList);
		getPresetedVList(cumMap.get("cum_type"), RefIndexEnum.CUMTYPE, orgId, voList);
		getPresetedVList(cumMap.get("cum_state"), RefIndexEnum.CUMSTATE, orgId, voList);

		return voList;
	}
	
	private void getPresetedVList(List<EnumVO> enumList, RefIndexEnum refIndex, Long orgId, List<VisitruleVO> voList) {
		
		Date date = new Date();
		
		for (EnumVO enumVO : enumList) {
			
			VisitruleVO vo = new VisitruleVO();
			
			vo.setTenantId(new Long(InvocationInfoProxy.getTenantid()));
			vo.setSysCreatedTime(date);
			vo.setSysCreatedUserId(new Long(InvocationInfoProxy.getParameter("id")));
			vo.setSysModifiedTime(date);
			vo.setSysModifiedUserId(new Long(InvocationInfoProxy.getParameter("id")));
			
			vo.setOrgId(orgId);
			vo.setRefIndex(refIndex.getValue());
			
			if (refIndex.getValue() == RefIndexEnum.CUMLEVEL.getValue()) {
				vo.setCumLevel(enumVO.getValue());
			}
			else if (refIndex.getValue() == RefIndexEnum.CUMTYPE.getValue()) {
				vo.setCumType(enumVO.getValue());
			}
			else if (refIndex.getValue() == RefIndexEnum.CUMSTATE.getValue()) {
				vo.setCumState(enumVO.getValue());
			}
			
			voList.add(vo);
		}
	}

	private List<VisitruleTaskcardVO> getPresetedVTList(Long visitruleId) {

		VisitruleTaskcardVO vtVO = new VisitruleTaskcardVO();
		vtVO.setVisitruleId(visitruleId);
		vtVO.setTaskcardId(new Long(1));
		vtVO.setOrderNum(1);
		vtVO.setRequired(1);
		vtVO.setIsPreseted(1);
		
		return Arrays.asList(vtVO);
	}
}
